package com.sky;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @Author 梁科
 * @Version 1.0
 * @ Date 2025/10/20 12:54
 */
@Aspect             // 指定该类为切面类
@Component          // 将该切面类注入到ioc容器中
public class AutoFillAspect {

    // 设置切入点，切入点id=方法名
    @Pointcut(value = "execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void myPointCut() {

    }

    /**
     * 设置前置通知：在目标方法执行前插入该方法
     *
     * @param joinPoint
     */
    @Before(value = "myPointCut()")
    public void showBeginLog(JoinPoint joinPoint) {
        // 获取方法标签
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取目标方法相关信息
        Method method = signature.getMethod();
        // 获取目标方法上的AutoFill注解
        AutoFill autoFillAnnotation = method.getAnnotation(AutoFill.class);
        // 获取该注解上的value属性（INSERT/UPDATE）
        OperationType type = autoFillAnnotation.value();
        // 获取方法参数（规定第一个参数对应mapper方法中的javabean参数）
        Object[] args = joinPoint.getArgs();
        Object entity = args[0];
        // 获取公共字段数据
        LocalDateTime localDateTime = LocalDateTime.now();
        Long id = BaseContext.getCurrentId();
        try {
            // 通过反射调用set方法，从而可以给被插入实体的属性赋值
            Method setCreateTimeMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setCreateUserMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method setUpdateTimeMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUserMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            if (type == OperationType.INSERT) {   // insert方法，需要插入4条公共信息
                setCreateTimeMethod.invoke(entity, localDateTime);
                setCreateUserMethod.invoke(entity, id);
                setUpdateTimeMethod.invoke(entity, localDateTime);
                setUpdateUserMethod.invoke(entity, id);
            } else if (type == OperationType.UPDATE) {  //update方法，需要插入2条公共信息
                setUpdateTimeMethod.invoke(entity, localDateTime);
                setUpdateUserMethod.invoke(entity, id);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
